﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using WebScrapper.Entities;
using App.Core.Extensions;
using WebScrapper.Helpers;
using System.Windows.Forms;

namespace WebScrapper.Implementations
{
    public class PolskaImplementation : BaseImplementation<Company>
    {
        private const String DOMAIN = "http://www.pkt.pl";

        public PolskaImplementation(RichTextBox txtStatus) : base(txtStatus)
        {
            
        }
        
        public override void StartScrapping(string category)
        {
            //this.Form.Cursor = Cursors.WaitCursor;
            //Form.btnStart.Enabled = false;
            //Read the Excell Spread Sheet with Categories and foreach category loop following process.
            //Start Processing a Category
            UpdateStatusText(String.Format("Starting Processing of Category: {0}", category));
            ProcessCategory(category);
            //this.Form.Cursor = Cursors.WaitCursor;
            //this.Form.btnStart.Enabled = true;
        }
        #region Processing Url
        protected void ProcessCategory(String category)
        {
            List<Company> extractedCompanies = new List<Company>();
            for (int pageNumber = 1; pageNumber < int.MaxValue; pageNumber++)
            {
                String url = PrepareRequestUrl(category, pageNumber);
                HtmlWeb hw = new HtmlWeb();
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                UpdateStatusText(String.Format("Loading HTML Document from: {0}", url));
                ///TODO: Enable following Code for Production Use
                doc = hw.Load(url);

                ///TODO: Disable Following Code for Production Use
                //doc.Load(@"D:\Projects\Web Scrapper\WebScrapper\Input Htmls\www.pk.pl\Polska.html");

                if (doc == null)
                    UpdateStatusText("Unable to Download HTML Document!");
                else
                {
                    var resultTable = doc.DocumentNode.SelectSingleNode("//table[@id='searchResultsTbl']");
                    ///Start Parsing from the Results Table
                    //if (resultTable == null || pageNumber > 1)
                    if (resultTable == null)
                    {
                        UpdateStatusText(String.Format("Total {1} Page(s) Navigated for Category: '{0}'", category, pageNumber - 1));
                        break;
                    }
                    else
                    {
                        var tbodys = resultTable.SelectNodes("tbody");
                        if (tbodys != null && tbodys.Count > 0)
                        {                            
                            foreach (HtmlNode tbody in tbodys)
                            {
                                var trs = tbody.SelectNodes("tr");
                                if (trs != null && trs.Count > 0)
                                {
                                    Company company = new Company();
                                    ProcessFirstRow(trs[0], company);
                                    extractedCompanies.Add(company);
                                }                                
                            }
                        }
                    }
                }
                ///TODO: For Testing
                //if (pageNumber > 0)
                //    break;
            }
            CreateExcel(extractedCompanies, category);
        }

        private string PrepareRequestUrl(string category, int pageNumber)
        {
            return String.Format("{0}/firmy/-/q_{1}/{2}/", DOMAIN, category, pageNumber);
        }
        #endregion

        /// <summary>
        /// Extracts Information from First Row
        /// </summary>
        /// <param name="tr"></param>
        /// <param name="company"></param>
        protected void ProcessFirstRow(HtmlNode tr, Company company)
        {
            var tds = tr.SelectNodes("td");
            if (tds != null && tds.Count > 0)
            {
                HtmlNode companyTd = tds[2];
                if (companyTd != null)
                {
                    var companyAnchor = companyTd.SelectNodes("h2")[0].SelectNodes("a")[0];
                    company.Name = CleanUpText(companyAnchor.InnerText);
                    company.Details = GetCompanyDetails(companyAnchor, company);

                    ///Address
                    var divs = companyTd.SelectNodes("div");
                    if (divs != null && divs.Count > 1)
                    {
                        var addressDiv = divs[1];
                        var spans = addressDiv.SelectNodes("span");
                        if (spans != null && spans.Count > 0)
                        {
                            company.PostalCode = spans[0].InnerText;
                            if (spans.Count > 1)
                                company.Locality = spans[1].InnerText;
                            if (spans.Count > 2)
                                company.StreetAddress = CleanUpText(spans[2].InnerText);
                        }
                        if (divs.Count > 2)
                        {
                            company.Category = divs[2].InnerText.StripHTML();
                            company.Category = company.Category.StartsWith("Branża:&nbsp;") ? CleanUpText(company.Category.Substring(13)) : CleanUpText(company.Category);
                        }
                    }
                    ///Extracting Email from <p class="email"><a href=''>abc@abc.com</p> formatted tag
                    var email = companyTd.Descendants("p")
                        .Where(P => P.GetAttributeValue("class", String.Empty) == "email")
                        .SelectMany(P => P.Descendants("a"));

                    if (email != null && email.Count() > 0)
                        company.Email = CleanUpText(email.ToList()[0].InnerHtml.StripHTML());

                    var telephone = companyTd.Descendants("p")
                        .Where(P => P.GetAttributeValue("class", String.Empty) == "tel");
                    //.SelectMany(P => P.Descendants("a"));
                    if (telephone != null && telephone.Count() > 0)
                        company.Telephone = CleanUpText(telephone.ToList()[0].InnerHtml.StripHTML());
                }
            }
        }

        private string GetCompanyDetails(HtmlNode companyAnchor, Company company)
        {
            String detailsUrl = companyAnchor.Attributes["href"].Value;
            if (!detailsUrl.IsNullOrEmpty())
            {
                detailsUrl = String.Format("{0}{1}", DOMAIN, detailsUrl);
                company.DetailsUrl = detailsUrl;
                HtmlWeb hw = new HtmlWeb();
                UpdateStatusText(String.Format("Downloading Details for: {0}, from: {1}", company.Name, detailsUrl));
                HtmlAgilityPack.HtmlDocument doc = hw.Load(detailsUrl);
                if (doc == null)
                    UpdateStatusText("Unable to Download Details HTML Document!");
                else
                {
                    var descriptionPara = doc.DocumentNode.SelectSingleNode("//p[@class='description']");
                    if (descriptionPara != null)
                    {
                        String details = descriptionPara.InnerHtml.Trim();
                        if (details.StartsWith("<b>Zakres działalności:</b>"))
                            details = details.Substring(27);

                        return details;
                    }
                }
            }
            return String.Empty;
        }
        protected void CreateExcel(List<Company> extractedCompanies, String category)
        {
            //throw new NotImplementedException();
            Console.WriteLine("{0}", extractedCompanies.Count);
            String outputFileName = DataExporter.ToExcel(extractedCompanies, true, String.Format("{0}.xls", category));
            UpdateStatusText(String.Format("'{0}{1}' Has been created successfully.", Environment.NewLine, outputFileName));
        }       

        public override string OutputFile(List<Company> collection, bool addColumnHeader, string outputFileName)
        {
            throw new NotImplementedException();
        }
    }
}
